package edu.scau.pos.service;

import edu.scau.core.exection.BusinessProcessException;
import edu.scau.core.util.ServletUtils;
import edu.scau.pos.domain.Product;
import edu.scau.pos.mapper.ProductMapper;
import edu.scau.pos.vo.ProductVo;
import edu.scau.pos.vo.SaleLineItemVo;
import edu.scau.sku.service.SkuColorSizeService;
import edu.scau.sku.service.SkuService;
import edu.scau.sku.vo.SkuColorSizeVo;
import edu.scau.sku.vo.SkuVo;
import edu.scau.system.domain.LoginUser;
import edu.scau.system.service.TokenService;
import edu.scau.tool.annotation.RequestLog;
import edu.scau.tool.domain.FileInfo;
import edu.scau.tool.sevice.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ProductServiceImpl implements ProductService{
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private SkuColorSizeService skuColorSizeService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private FileService fileService;
    @Override
    public ProductVo findProductBySn(String productSn) {
        ProductVo productVo=productMapper.findProductBySn(productSn);
        String url=productVo.getUrl();
        if (url.length() < 255) {
            String key = "product/"+url.replaceAll("[:/]", "") + ".jpg";
            String minioUrl=fileService.getUrlByName(key);
            productVo.setUrl(Objects.equals(minioUrl, "") ? url : minioUrl);
        }
        return productVo;
    }

    @Override
    public List<ProductVo> findAllProductAndStock() {
        return this.upsertDataUrl(productMapper.findAllProductAndStock());
    }

    @Override
    public List<Map<String, List<ProductVo>>> listAll() {
        return this.AggregateProductList(this.upsertDataUrl(productMapper.listAll()));
    }

    @Override
    public List<ProductVo> findProductList(ProductVo productVo) {
        return this.upsertDataUrl(productMapper.findProductList(productVo));
    }

    @Override
    public int insertProduct(ProductVo productVo) {
        System.out.println("pSerIml:55 "+productVo.toString());
        if(productVo.getProductSn().isEmpty()){
            throw new IllegalArgumentException("商品编号不能为空！");
        }
        if(isExisted(productVo.getProductSn())){
            throw new IllegalArgumentException("商品编号已存在");
        }
        if(productVo.getCategoryId() != null){
         if (!categoryService.isExisted(productVo.getCategoryId()))  {
             throw new IllegalArgumentException("不存在该分类！");
         }
        }
        LoginUser loginUser=tokenService.getLoginUser(ServletUtils.getRequest());
        String createBy = loginUser.getUsername();
        Date createTime = new Date();
        Product product=new Product(productVo);
        product.setCreateBy(createBy);
        product.setCreateTime(createTime);
        return productMapper.insertProduct(product);
    }

    @Override
    public int updateProduct(ProductVo productVo) {
        if(productVo.getProductSn().isEmpty()){
            throw new IllegalArgumentException("商品编号不能为空！");
        }
        if(! isExisted(productVo.getProductSn())){
            throw new IllegalArgumentException("不存在的商品！");
        }
        if(productVo.getCategoryId()!= null ){
            if (!categoryService.isExisted(productVo.getCategoryId()))  {
                throw new IllegalArgumentException("不存在该分类！");
            }
        }
        LoginUser loginUser=tokenService.getLoginUser(ServletUtils.getRequest());
        String updateBy = loginUser.getUsername();
        Date updateTime = new Date();
        Product product=new Product(productVo);
        product.setUpdateBy(updateBy);
        product.setUpdateTime(updateTime);
        return productMapper.updateProduct(product);
    }

    @Override
    public int deleteProductBySn(String productSn) {
        return productMapper.deleteProductBySn(productSn);
    }

    @Override
    public boolean isExisted(String productSn) {
        return productMapper.isExisted(productSn) >0;
    }

    @Override
    public int findStockBySn(String productSn) {
        ProductVo productVo=productMapper.findProductBySn(productSn);
        return productVo.getSkuVo().getStock();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertProductAndSku(ProductVo productVo) {
        if(productVo.getProductSn().isEmpty()){
            throw new IllegalArgumentException("商品编号不能为空！");
        }
        if(isExisted(productVo.getProductSn())){
            throw new IllegalArgumentException("商品库存已存在！");
        }
        if(productVo.getCategoryId()!= null ){
            if (!categoryService.isExisted(productVo.getCategoryId()))  {
                throw new IllegalArgumentException("不存在该分类！");
            }
        }
        //设置商品信息
        LoginUser loginUser=tokenService.getLoginUser(ServletUtils.getRequest());
        String createBy = loginUser.getUsername();
        Date createTime = new Date();
        Product product=new Product(productVo);
        product.setCreateBy(createBy);
        product.setCreateTime(createTime);
        //设置库存编号
        String skuCode = skuColorSizeService.generateSkuCode(productVo.getProductSn(),productVo.getSkuCode());
        product.setSkuCode(skuCode);
        //插入商品
        int res=productMapper.insertProduct(product);
        //插入库存详情
        SkuColorSizeVo skuColorSizeVo = new SkuColorSizeVo(skuCode,productVo.getColor(),productVo.getSize());
        int r1=skuColorSizeService.insertSkuColorSize(skuColorSizeVo);
        if(r1 <= 0){
            log.info("skuColorSizeService插入失败");
            throw new BusinessProcessException("插入失败");
        }
        //插入库存
        SkuVo skuVo=productVo.getSkuVo();
        if(skuVo ==null ){
            skuVo=new SkuVo();
        }
        skuVo.setSkuCode(skuCode);
        String skuName = productVo.getProductName();
        skuVo.setSkuName(skuName);
        int r2=skuService.insertSku(skuVo);
        if(r2 <= 0){
            log.info("skuService插入失败");
            throw new BusinessProcessException("插入失败");
        }
        return res;
    }

    /**
     * 批量更新库存
     * @param saleLineItemVoList
     * @return
     */
    @Override
    @Transactional
    public int batchUpdateStock(List<SaleLineItemVo> saleLineItemVoList) {
        Map<String, Integer> skuMap = saleLineItemVoList.stream().collect(Collectors.toMap(
                item -> getSkuCodeFromProductSn(item.getProductSn()),
                SaleLineItemVo::getQuantity
        ));
        return skuService.batchUpdateStock(skuMap);
        //return productMapper.batch1UpdateStock(saleLineItemVoList);
    }

    @Override
    public String getSkuCodeFromProductSn(String productSn){
        return productMapper.findProductBySn(productSn).getSkuCode();
    }


    @Override
    public int batchAddStock(List<SaleLineItemVo> saleLineItemVoList) {
        Map<String, Integer> skuMap = saleLineItemVoList.stream().collect(Collectors.toMap(
                item -> getSkuCodeFromProductSn(item.getProductSn()),
                SaleLineItemVo::getQuantity
        ));
        return skuService.batchAddStock(skuMap);
       // return productMapper.batchAddStock(saleLineItemVoList);
    }
   @Override
    public List<Map<String,List<ProductVo>>> AggregateProductList(List<ProductVo> productVoList){
        List<Map<String,List<ProductVo>>> list=new ArrayList<>();
        Map<String,List<ProductVo>> listOfameProductName=new HashMap<>();
        Set<String> productNameSet=new HashSet<>();
        for(ProductVo productVo:productVoList){
            productNameSet.add(productVo.getProductName());
        }
        for (String s : productNameSet) {
            ProductVo productVo=new ProductVo();
            productVo.setProductName(s);
            List<ProductVo> productVoList1=this.upsertDataUrl(productMapper.findProductList(productVo));
            listOfameProductName.put(s,productVoList1);
        }
        list.add(listOfameProductName);
        return list;
    }

    @Override
    public List<Map<String, List<ProductVo>>> AggregateProductListLimitOne(List<ProductVo> productVoList) {
        List<Map<String,List<ProductVo>>> list=new ArrayList<>();
        Map<String,List<ProductVo>> listOfameProductName=new HashMap<>();
        Set<String> productNameSet=new HashSet<>();
        for(ProductVo productVo:productVoList){
            productNameSet.add(productVo.getProductName());
        }
        for (String s : productNameSet) {
            ProductVo productVo=new ProductVo();
            productVo.setProductName(s);
            List<ProductVo> productVoList1=this.upsertDataUrl(productMapper.findProductListLimitOne(productVo));
            listOfameProductName.put(s,productVoList1);
        }
        list.add(listOfameProductName);
        return list;
    }


    @Override
    public List<Map<String, List<ProductVo>>> getProductOfCategory(long categoryId) {
        ProductVo productVo=new ProductVo();
        productVo.setCategoryId(categoryId);
        List<ProductVo> productVoList=this.upsertDataUrl(productMapper.findProductList(productVo));
        return this.AggregateProductList(productVoList);
    }

    @Override
    @RequestLog
    public String uploadFile(MultipartFile file) {
        FileInfo fileInfo =  fileService.uploadFile(file);
        String fileName = fileInfo.getFileName();
        String url = fileService.getUrlByName(fileName);
        return url;
    }

    @Override
    public List<Map<String, List<ProductVo>>> listAllOfOne() {
        List<ProductVo> productVoList = this.upsertDataUrl(productMapper.listAll());
        return this.AggregateProductListLimitOne(productVoList);
    }

    @Override
    public List<ProductVo> listAllOfDb() {
        return this.upsertDataUrl(productMapper.listAll());
    }

    @Override
    public List<Map<String, List<ProductVo>>> listAllOfOneByCategory(long categoryId) {
        ProductVo productVo=new ProductVo();
        productVo.setCategoryId(categoryId);
        List<ProductVo> productVoList=this.upsertDataUrl(productMapper.findProductList(productVo));
        return this.AggregateProductListLimitOne(productVoList);
    }

    @Override
    public List<ProductVo> listAllOfOneByProductName(String productName) {
        ProductVo productVo=new ProductVo();
        productVo.setProductName(productName);
        List<ProductVo> productVoList=this.upsertDataUrl(productMapper.findProductList(productVo));
        return productVoList;
    }

    public List<ProductVo> upsertDataUrl(List<ProductVo> productVoList){
        for (ProductVo productVo : productVoList) {
            String url=productVo.getUrl();
            if (url.length() > 255) {
                continue;
            }
            String key = url.replaceAll("[:/]", "") + ".jpg";
            String minioUrl=fileService.getUrlByName("product/"+key);
            productVo.setUrl(Objects.equals(minioUrl, "") ? url : minioUrl);
        }
        return productVoList;
    }

}
